﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Forms;
using ProgNetComponents.Utils;

namespace ProgNetComponents.Logs
{
    /// <summary>
    /// Logger
    /// </summary>
    public class Logger
    {
        /// <summary>
        /// Occurs when [exception loggend].
        /// </summary>
        public static event LogExceptionTextHandler ExceptionLoggend;

        /// <summary>
        /// Initializes the <see cref="Logger"/> class.
        /// </summary>
        static Logger()
        {
            MaxAllowedInheritance = 2;
            MaxPropsAllowed = 10;
            SkipTypes = new Type[] { 
                typeof(string), 
                typeof(int), 
                typeof(decimal), 
                typeof(double),
                typeof(float),
                typeof(bool),
                typeof(Type),
                typeof(System.RuntimeTypeHandle), 
                typeof(System.Reflection.MemberInfo),
                typeof(Module) };
        }

        /// <summary>
        /// Gets or sets the maximum allowed inheritance.
        /// </summary>
        /// <value>
        /// The maximum allowed inheritance.
        /// </value>
        public static int MaxAllowedInheritance { get; set; }
        /// <summary>
        /// Gets or sets the maximum props allowed.
        /// </summary>
        /// <value>
        /// The maximum props allowed.
        /// </value>
        public static int MaxPropsAllowed { get; set; }
        /// <summary>
        /// Gets or sets the skip types.
        /// </summary>
        /// <value>
        /// The skip types.
        /// </value>
        public static Type[] SkipTypes
        {
            get;
            set;
        }
        #region static
        /// <summary>
        /// Initializes the default logger.
        /// </summary>
        /// <param name="logFile">The log file.</param>
        /// <param name="currentLogType">Type of the current log.</param>
        /// <param name="logType">Type of the log.</param>
        /// <param name="additionalLogging">if set to <c>true</c> [additional logging].</param>
        public static void InitDefaultLogger(string logFile = "error.log", LogType currentLogType = LogType.Error, LogType logType = LogType.Error, bool additionalLogging = false)
        {
            ProgNetComponents.Logs.Logger.CurrentLogType = currentLogType;
            ProgNetComponents.Logs.LoggerProperties p = new ProgNetComponents.Logs.LoggerProperties();

            p.AdditionalStackTraceMaxLines = 10;
            if(!logFile.XMatch("^[\\w]:"))
                logFile = Application.StartupPath + "\\"+logFile.TrimStart('\\');
            p.FileName = logFile;
            DefaultBool additionalBool = additionalLogging ? DefaultBool.True: DefaultBool.False;

            p.LogAdditionalStackTrace = additionalBool;
            p.LogDate = ProgNetComponents.Utils.DefaultBool.True;
            p.LogExceptionName = ProgNetComponents.Utils.DefaultBool.True;
            p.LogExceptionProperties = additionalBool;
            p.LogInnerExceptios = additionalBool;
            p.LogLogType = ProgNetComponents.Utils.DefaultBool.True;
            p.LogStackTrace = ProgNetComponents.Utils.DefaultBool.True;
            p.LogTime = ProgNetComponents.Utils.DefaultBool.True;
            p.LogType = logType;
            p.StackTraceMaxLines = 11;
            p.LogExceptionMessage = ProgNetComponents.Utils.DefaultBool.True;
            Logger.InitLoggerProperties("", p);
        }

        /// <summary>
        /// _Properties
        /// </summary>
        private static Dictionary<string, LoggerProperties> _Properties = new Dictionary<string, LoggerProperties>();
        /// <summary>
        /// _LogFileInfo
        /// </summary>
        private static Dictionary<string, LogFileInfo> _LogFileInfo = new Dictionary<string, LogFileInfo>();
        /// <summary>
        /// Gets the log file information.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <returns></returns>
        private static LogFileInfo GetLogFileInfo(string file)
        {
            string key = file.ToUpper();
            if(!_LogFileInfo.ContainsKey(key))
                _LogFileInfo.Add(key, new LogFileInfo(file));
            return _LogFileInfo[key];
        }
        /// <summary>
        /// Gets the log files.
        /// </summary>
        /// <returns></returns>
        public static List<string> GetLogFiles()
        {
            List<string> list = new List<string>();
            foreach (KeyValuePair<string, LogFileInfo> kvp in _LogFileInfo)
                list.Add(kvp.Value.FileName);
            return list;
        }
        /// <summary>
        /// Cleans up.
        /// </summary>
        public static void CleanUp()
        {
            foreach (KeyValuePair<string, LogFileInfo> kvp in _LogFileInfo)
                kvp.Value.Dispose();
            _LogFileInfo.Clear();
            _Properties.Clear();
        }
        /// <summary>
        /// Initializes the logger properties.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="properties">The properties.</param>
        /// <param name="fullAssign">if set to <c>true</c> [full assign].</param>
        public static void InitLoggerProperties(Type target, LoggerProperties properties, bool fullAssign = true)
        {
            InitLoggerProperties(target.FullName, properties, fullAssign);
        }

        /// <summary>
        /// Initializes the logger properties.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="properties">The properties.</param>
        /// <param name="fullAssign">if set to <c>true</c> [full assign].</param>
        public static void InitLoggerProperties(string target, LoggerProperties properties, bool fullAssign = true)
        {
            target = target.AsString();
            if (!_Properties.ContainsKey(target))
            {
                _Properties.Add(target, new LoggerProperties());
            }
            _Properties[target].Assign(properties, fullAssign);
        }
        /// <summary>
        /// Removes the logger properties.
        /// </summary>
        /// <param name="target">The target.</param>
        public static void RemoveLoggerProperties(string target)
        {
            if (_Properties.ContainsKey(target))
                _Properties.Remove(target);
        }
        /// <summary>
        /// Gets the properties.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        public static LoggerProperties GetProperties(string target)
        {
            target = target.AsString();
            if (_Properties.ContainsKey(target))
            {
                return _Properties[target];
            }
            return null;
        }

        /// <summary>
        /// _Default
        /// </summary>
        private static Logger _Default;
        /// <summary>
        /// Gets the default.
        /// </summary>
        /// <value>
        /// The default.
        /// </value>
        public static Logger Default
        {
            get
            {
                if (_Default == null)
                    _Default = new Logger();
                return _Default;
            }
        }

        /// <summary>
        /// Gets or sets the type of the current log.
        /// </summary>
        /// <value>
        /// The type of the current log.
        /// </value>
        public static LogType CurrentLogType
        {
            get;
            set;
        }
        #endregion

        /// <summary>
        /// Target
        /// </summary>
        private string Target;
        /// <summary>
        /// Initializes a new instance of the <see cref="Logger"/> class.
        /// </summary>
        /// <param name="target">The target.</param>
        public Logger(string target)
        {
            Target = target;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Logger"/> class.
        /// </summary>
        /// <param name="type">The type.</param>
        public Logger(Type type):this(type.FullName)
        {
        }
        /// <summary>
        /// Prevents a default instance of the <see cref="Logger"/> class from being created.
        /// </summary>
        private Logger()
            : this("")
        {
        }

        /// <summary>
        /// Gets the previous target.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        private static string GetPreviousTarget(string target)
        {
            if (target != null)
            {
                int idx = target.LastIndexOf('.');
                if (idx > -1)
                    return target.Substring(0, idx);
            }
            return string.Empty;
        }

        /// <summary>
        /// Gets the best properties for target.
        /// </summary>
        /// <param name="targetToFind">The target to find.</param>
        /// <returns></returns>
        public static LoggerProperties GetBestPropertiesForTarget(string targetToFind)
        {
            LoggerProperties p = new LoggerProperties();
            string target = targetToFind;
            while (!p.IsFullyDefined)
            {
                if (_Properties.ContainsKey(target))
                {
                    if (p.FileName.IsNullOrEmpty() && _Properties[target].FileName.IsNotNullOrEmpty())
                        p.FileName = _Properties[target].FileName;

                    if (p.AdditionalStackTraceMaxLines == -1 && _Properties[target].AdditionalStackTraceMaxLines != -1)
                        p.AdditionalStackTraceMaxLines = _Properties[target].AdditionalStackTraceMaxLines;

                    if (p.StackTraceMaxLines == -1 && _Properties[target].StackTraceMaxLines != -1)
                        p.StackTraceMaxLines = _Properties[target].StackTraceMaxLines;

                    if (p.LogType == LogType.Default && _Properties[target].LogType != LogType.Default)
                        p.LogType = _Properties[target].LogType;

                    if (p.LogInnerExceptios == DefaultBool.Default && _Properties[target].LogInnerExceptios != DefaultBool.Default)
                        p.LogInnerExceptios = _Properties[target].LogInnerExceptios;

                    if (p.LogAdditionalStackTrace == DefaultBool.Default && _Properties[target].LogAdditionalStackTrace != DefaultBool.Default)
                        p.LogAdditionalStackTrace = _Properties[target].LogAdditionalStackTrace;

                    if (p.LogStackTrace == DefaultBool.Default && _Properties[target].LogStackTrace != DefaultBool.Default)
                        p.LogStackTrace = _Properties[target].LogStackTrace;

                    if (p.LogDate == DefaultBool.Default && _Properties[target].LogDate != DefaultBool.Default)
                        p.LogDate = _Properties[target].LogDate;

                    if (p.LogTime == DefaultBool.Default && _Properties[target].LogTime != DefaultBool.Default)
                        p.LogTime = _Properties[target].LogTime;

                    if (p.LogLogType == DefaultBool.Default && _Properties[target].LogLogType != DefaultBool.Default)
                        p.LogLogType = _Properties[target].LogLogType;

                    if (p.LogExceptionName == DefaultBool.Default && _Properties[target].LogExceptionName != DefaultBool.Default)
                        p.LogExceptionName = _Properties[target].LogExceptionName;

                    if (p.LogExceptionMessage == DefaultBool.Default && _Properties[target].LogExceptionMessage != DefaultBool.Default)
                        p.LogExceptionMessage = _Properties[target].LogExceptionMessage;

                    if (p.LogExceptionProperties == DefaultBool.Default && _Properties[target].LogExceptionProperties != DefaultBool.Default)
                        p.LogExceptionProperties = _Properties[target].LogExceptionProperties;
                }
                if (target.IsNullOrEmpty())
                    break;
                target = GetPreviousTarget(target);
            }
            return p;
        }
        /// <summary>
        /// Logs the specified MSG.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="type">The type.</param>
        /// <param name="ex">The ex.</param>
        /// <exception cref="System.ArgumentException">type can not be LogType.Default</exception>
        public void Log(string msg, LogType type, Exception ex)
        {
            if (type == LogType.Default)
                throw new ArgumentException("type can not be LogType.Default");


            LoggerProperties p = GetBestPropertiesForTarget(Target);
            string target = Target;
            
            if (CurrentLogType != LogType.Default && p.IsFullyDefined && p.LogType >= CurrentLogType)
            {
                StringBuilder sb = new StringBuilder();
                int skipFrames = 3;
                StackFrame sf = new StackFrame(skipFrames);
                MethodBase mb = sf.GetMethod();
                if (p.LogLogType == DefaultBool.True)
                    sb.Append("[" + type.ToString() + "] ");
                if (p.LogDate == DefaultBool.True)
                    sb.Append(DateTime.Now.ToString("d") + " ");
                if (p.LogTime == DefaultBool.True)
                    sb.Append(DateTime.Now.ToString("T") + " ");
                if (p.LogExceptionName == DefaultBool.True)
                {
                    if (ex != null)
                        sb.Append("[" + ex.GetType().FullName + "] ");
                }
                if (msg.IsNotNullOrEmpty())
                    sb.AppendLine(msg);
                
                AppendExceptionInfo(sb, p, ex);
                LogFileInfo li = GetLogFileInfo(p.FileName);
                lock (li.FileSynch)
                {
                    li.WriteLine(sb.ToString().Trim());
                    if (ExceptionLoggend != null)
                        ExceptionLoggend(new LogExceptionEventArgs(msg, type, ex, sb.ToString().Trim()));
                }
            }
        }

        /// <summary>
        /// Adds the properties.
        /// </summary>
        /// <param name="sb">The sb.</param>
        /// <param name="ex">The ex.</param>
        /// <param name="count">The count.</param>
        /// <param name="maxAllowedInheritance">The maximum allowed inheritance.</param>
        /// <param name="maxPropsAllowed">The maximum props allowed.</param>
        /// <param name="skipTypes">The skip types.</param>
        private static void AddProperties(StringBuilder sb, object ex, int count, int maxAllowedInheritance, int maxPropsAllowed, params Type[] skipTypes)
        {
            PropertyInfo[] pis = ex.GetType().GetProperties();
            
            object val;
            string tabs = "";
            for (int i = 0; i < count; i++)
                tabs += "\t";
            int ct = 0;

            foreach (PropertyInfo pi in pis)
            {
                if (ct >= maxPropsAllowed)
                    break;

                try
                {
                    val = pi.GetValue(ex, null);
                    if (val.IsNotNull())
                    {
                        sb.AppendLine(tabs + "{" + pi.Name + " = " + val.AsString() + " } (" + pi.PropertyType.AsString() + ")");
                        ct++;
                    }
                    if (val.IsNotNull() && count < maxAllowedInheritance)
                    {
                        if (val is System.Collections.ICollection)
                            if (((System.Collections.ICollection)val).Count == 0)
                                continue;

                        if (skipTypes != null)
                        {
                            bool cont = false;
                            foreach (var t in skipTypes)
                            {
                                if (t.IsAssignableFrom(val.GetType()))
                                {
                                    cont = true;
                                    break;
                                }
                            }
                            if (cont)
                                continue;
                        }
                        AddProperties(sb, val, count + 1, maxAllowedInheritance, maxPropsAllowed, skipTypes);
                    }
                }
                catch { }
            }
        }
        /// <summary>
        /// Appends the exception information.
        /// </summary>
        /// <param name="sb">The sb.</param>
        /// <param name="p">The p.</param>
        /// <param name="ex">The ex.</param>
        /// <param name="maxAllowedInheritance">The maximum allowed inheritance.</param>
        /// <param name="maxPropsAllowed">The maximum props allowed.</param>
        /// <param name="skipTypes">The skip types.</param>
        public static void AppendExceptionInfo(StringBuilder sb, LoggerProperties p, Exception ex, int maxAllowedInheritance, int maxPropsAllowed, params Type[] skipTypes)
        {
            if (p.LogExceptionProperties == DefaultBool.True && ex != null)
            {
                PropertyInfo[] pis = ex.GetType().GetProperties();
                sb.AppendLine("\tException:");
                AddProperties(sb, ex, 1, maxAllowedInheritance, maxPropsAllowed, skipTypes);
            }
            else
            {
                if (p.LogExceptionMessage == DefaultBool.True && ex != null && ex.Message != null)
                {
                    sb.AppendLine("\tException:");
                    sb.AppendLine(ex.Message);
                }

                if (p.LogStackTrace == DefaultBool.True && ex != null && ex.StackTrace != null)
                {
                    sb.AppendLine("\t-------------- Stack Trace ------------------");
                    if (p.StackTraceMaxLines <= 0)
                        sb.AppendLine(ex.StackTrace);
                    else
                    {
                        List<string> stack = ex.StackTrace.ToLines(true, true);
                        for (int i = 0; i <= p.StackTraceMaxLines; i++)
                        {
                            if (stack.Count > i)
                                sb.AppendLine(stack[i]);
                            else
                                break;
                        }
                    }
                }
            }
            if (p.LogAdditionalStackTrace == DefaultBool.True)
            {
                sb.AppendLine("\t-------------- Additional Stack Trace ------------------");
                StackTrace st = new StackTrace(3);
                if (p.AdditionalStackTraceMaxLines == -1)
                    sb.AppendLine(st.ToString());
                else
                {
                    List<string> stack = st.ToString().ToLines(true, true);
                    for (int i = 0; i <= p.AdditionalStackTraceMaxLines; i++)
                    {
                        if (stack.Count > i)
                            sb.AppendLine(stack[i]);
                        else
                            break;
                    }
                }
            }
            if (p.LogInnerExceptios == DefaultBool.True && ex != null && ex.InnerException != null)
            {
                sb.AppendLine("\t-------------- Inner Exception ------------------");
                AppendExceptionInfo(sb, p, ex.InnerException);
            }
            sb.AppendLine("");

        }
        /// <summary>
        /// Appends the exception information.
        /// </summary>
        /// <param name="sb">The sb.</param>
        /// <param name="p">The p.</param>
        /// <param name="ex">The ex.</param>
        public static void AppendExceptionInfo(StringBuilder sb, LoggerProperties p, Exception ex)
        {
            AppendExceptionInfo(sb, p, ex, MaxAllowedInheritance, MaxPropsAllowed, SkipTypes);
        }
        /// <summary>
        /// Logs the error.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogError(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.Error, ex); 
        }
        /// <summary>
        /// Logs the information.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogInfo(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.Info, ex);
        }
        /// <summary>
        /// Logs the warning.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogWarning(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.Warning, ex);
        }
        /// <summary>
        /// Logs the debug.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogDebug(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.Debug, ex);
        }
        /// <summary>
        /// Logs the internal.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogInternal(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.Internal, ex);
        }
        /// <summary>
        /// Logs all.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogAll(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.All, ex);
        }
        /// <summary>
        /// Logs the user1.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogUser1(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.User1, ex);
        }
        /// <summary>
        /// Logs the user2.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogUser2(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.User2, ex);
        }
        /// <summary>
        /// Logs the user3.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        public void LogUser3(string message = "", Exception ex = null)
        {
            Log(message, Logs.LogType.User3, ex);
        }

        /// <summary>
        /// 
        /// </summary>
        private class LogFileInfo : IDisposable
        {
            /// <summary>
            /// Gets or sets the stream writer.
            /// </summary>
            /// <value>
            /// The stream writer.
            /// </value>
            public StreamWriter StreamWriter
            {
                get;
                private set;
            }
            /// <summary>
            /// Gets or sets the file stream.
            /// </summary>
            /// <value>
            /// The file stream.
            /// </value>
            public FileStream FileStream
            {
                get;
                private set;
            }
            /// <summary>
            /// Gets or sets the name of the file.
            /// </summary>
            /// <value>
            /// The name of the file.
            /// </value>
            public string FileName
            {
                get;
                private set;
            }
            /// <summary>
            /// Gets or sets the file synch.
            /// </summary>
            /// <value>
            /// The file synch.
            /// </value>
            public object FileSynch
            {
                get;
                set;
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="LogFileInfo"/> class.
            /// </summary>
            /// <param name="file">The file.</param>
            public LogFileInfo(string file)
            {
                FileName = file;
                FileSynch = new object();
                FileStream = System.IO.File.Open(file, System.IO.FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                StreamWriter = new StreamWriter(FileStream);
            }

            /// <summary>
            /// Writes the specified message.
            /// </summary>
            /// <param name="message">The message.</param>
            public void Write(string message)
            {
                StreamWriter.Write(message);
                StreamWriter.Flush();
            }
            /// <summary>
            /// Writes the line.
            /// </summary>
            /// <param name="message">The message.</param>
            public void WriteLine(string message)
            {
                StreamWriter.WriteLine(message);
                StreamWriter.Flush();
            }

            /// <summary>
            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
            /// </summary>
            public void Dispose()
            {
                try
                {
                    if (StreamWriter != null)
                        StreamWriter.Close();
                    if (FileStream != null)
                        FileStream.Close();
                }
                catch { }
            }
        }
    }
    /// <summary>
    /// 
    /// </summary>
    public class LogExceptionEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LogExceptionEventArgs"/> class.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="type">The type.</param>
        /// <param name="ex">The ex.</param>
        /// <param name="fullLogMessage">The full log message.</param>
        public LogExceptionEventArgs(string msg, LogType type, Exception ex, string fullLogMessage)
        {
            this.LogType = type;
            this.Exception = ex;
            this.AdditionalMessage = msg;
            this.FullMessage = fullLogMessage;
        }
        /// <summary>
        /// Gets the type of the log.
        /// </summary>
        /// <value>
        /// The type of the log.
        /// </value>
        public LogType LogType
        {
            get;
            private set;
        }
        /// <summary>
        /// Gets the additional message.
        /// </summary>
        /// <value>
        /// The additional message.
        /// </value>
        public string AdditionalMessage
        {
            get;
            private set;
        }
        /// <summary>
        /// Gets the exception.
        /// </summary>
        /// <value>
        /// The exception.
        /// </value>
        public Exception Exception
        {
            get;
            private set;
        }
        /// <summary>
        /// Gets the full message.
        /// </summary>
        /// <value>
        /// The full message.
        /// </value>
        public string FullMessage
        {
            get;
            private set;
        }

    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="exceptionFullInfo">The <see cref="LogExceptionEventArgs"/> instance containing the event data.</param>
    public delegate void LogExceptionTextHandler(LogExceptionEventArgs exceptionFullInfo);

    /// <summary>
    /// 
    /// </summary>
    public class LoggerProperties
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LoggerProperties"/> class.
        /// </summary>
        public LoggerProperties()
        {
            LogInnerExceptios = DefaultBool.Default;
            LogStackTrace = DefaultBool.Default;
            LogAdditionalStackTrace = DefaultBool.Default;
            LogType = Logs.LogType.Default;
            StackTraceMaxLines = -1;
            AdditionalStackTraceMaxLines = -1;
            FileName = "";
        }

        /// <summary>
        /// Gets or sets the name of the file.
        /// </summary>
        /// <value>
        /// The name of the file.
        /// </value>
        public string FileName
        {
            get;
            set;
        }

        /// <summary>
        /// StackTrace maximum lines count; 0: all; -1: ignore
        /// </summary>
        /// <value>
        /// The stack trace maximum lines.
        /// </value>
        public int StackTraceMaxLines
        {
            get;
            set;
        }
        /// <summary>
        /// AdditionalStackTrace maximum lines count; 0: all; -1: ignore
        /// </summary>
        /// <value>
        /// The additional stack trace maximum lines.
        /// </value>
        public int AdditionalStackTraceMaxLines
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the type of the log.
        /// </summary>
        /// <value>
        /// The type of the log.
        /// </value>
        public LogType LogType
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the log inner exceptios.
        /// </summary>
        /// <value>
        /// The log inner exceptios.
        /// </value>
        public DefaultBool LogInnerExceptios
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the log additional stack trace.
        /// </summary>
        /// <value>
        /// The log additional stack trace.
        /// </value>
        public DefaultBool LogAdditionalStackTrace
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the log stack trace.
        /// </summary>
        /// <value>
        /// The log stack trace.
        /// </value>
        public DefaultBool LogStackTrace
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the log date.
        /// </summary>
        /// <value>
        /// The log date.
        /// </value>
        public DefaultBool LogDate
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the log time.
        /// </summary>
        /// <value>
        /// The log time.
        /// </value>
        public DefaultBool LogTime
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the type of the log log.
        /// </summary>
        /// <value>
        /// The type of the log log.
        /// </value>
        public DefaultBool LogLogType
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the name of the log exception.
        /// </summary>
        /// <value>
        /// The name of the log exception.
        /// </value>
        public DefaultBool LogExceptionName
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the log exception message.
        /// </summary>
        /// <value>
        /// The log exception message.
        /// </value>
        public DefaultBool LogExceptionMessage
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets the log exception properties.
        /// </summary>
        /// <value>
        /// The log exception properties.
        /// </value>
        public DefaultBool LogExceptionProperties
        {
            get;
            set;
        }

        /// <summary>
        /// Gets a value indicating whether [is fully defined].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [is fully defined]; otherwise, <c>false</c>.
        /// </value>
        public bool IsFullyDefined
        {
            get
            {
                return FileName.IsNotNull() &&
                        LogInnerExceptios != DefaultBool.Default &&
                        LogAdditionalStackTrace != DefaultBool.Default &&
                        LogStackTrace != DefaultBool.Default &&
                        LogDate != DefaultBool.Default &&
                        LogTime != DefaultBool.Default &&
                        LogLogType != DefaultBool.Default &&
                        LogExceptionName != DefaultBool.Default &&
                        LogExceptionProperties != DefaultBool.Default &&
                        LogType != Logs.LogType.Default &&
                        LogExceptionMessage != DefaultBool.Default &&
                        (LogStackTrace == DefaultBool.False || StackTraceMaxLines > -1) &&
                        (LogAdditionalStackTrace == DefaultBool.False || AdditionalStackTraceMaxLines > -1);
            }
        }
        /// <summary>
        /// Assigns the specified p.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <param name="fullAssign">if set to <c>true</c> [full assign].</param>
        internal void Assign(LoggerProperties p, bool fullAssign = true)
        {
            if (fullAssign || p.AdditionalStackTraceMaxLines > -1)
                this.AdditionalStackTraceMaxLines = p.AdditionalStackTraceMaxLines;
            if (fullAssign || p.FileName.IsNotNull())
                this.FileName = p.FileName;
            if (fullAssign || p.LogAdditionalStackTrace != DefaultBool.Default)
                this.LogAdditionalStackTrace = p.LogAdditionalStackTrace;
            if (fullAssign || p.LogDate != DefaultBool.Default)
                this.LogDate = p.LogDate;
            if (fullAssign || p.LogExceptionName != DefaultBool.Default)
                this.LogExceptionName = p.LogExceptionName;
            if (fullAssign || p.LogExceptionProperties != DefaultBool.Default)
                this.LogExceptionProperties = p.LogExceptionProperties;
            if (fullAssign || p.LogInnerExceptios != DefaultBool.Default)
                this.LogInnerExceptios = p.LogInnerExceptios;
            if (fullAssign || p.LogLogType != DefaultBool.Default)
                this.LogLogType = p.LogLogType;
            if (fullAssign || p.LogStackTrace != DefaultBool.Default)
                this.LogStackTrace = p.LogStackTrace;
            if (fullAssign || p.LogTime != DefaultBool.Default)
                this.LogTime = p.LogTime;
            if (fullAssign || p.LogType != Logs.LogType.Default)
                this.LogType = p.LogType;
            if (fullAssign || p.LogExceptionMessage != DefaultBool.Default)
                this.LogExceptionMessage = p.LogExceptionMessage;
            if (fullAssign || p.StackTraceMaxLines != -1)
                this.StackTraceMaxLines = p.StackTraceMaxLines;
        }
    }
}
